package service;

import config.SSLProperties;
import model.request.*;
import model.response.*;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
import remoting.WXPayRemoting;
import retrofit2.Call;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.simplexml.SimpleXmlConverterFactory;
import utils.BuildDataUtil;
import utils.RandomUtil;
import utils.SignatureUtil;
import utils.XmlUtil;

import java.io.IOException;
import java.util.UUID;

public class WXPayService {

    private static final String SANDBOXNEW = "/sandboxnew/";

    private SSLProperties sslProperties;

    private String gateway;
    /**
     * 公众号appId
     */
    private String appId;
    /**
     * 公众号appSecret
     */
    private String appSecret;
    /**
     * 商户号
     */
    private String mchId;
    /**
     * 商户密钥
     */
    private String mchKey;


    public WXPayService(String gateway, String appId, String appSecret, String mchId, String mchKey){
        sslProperties = new SSLProperties();
        this.gateway = gateway;
        this.appId = appId;
        this.appSecret = appSecret;
        this.mchId = mchId;
        this.mchKey = mchKey;
    }

    /*微信支付预下单接口*/
    public WXPayResponse appPrePay(PayRequest request) {
        WXPayRequest wxPayRequest = new WXPayRequest();
        wxPayRequest.setOutTradeNo(request.getOrderNO());
        wxPayRequest.setTotalFee(request.getAmount());
        wxPayRequest.setBody(request.getGoodsName());
        wxPayRequest.setAttach(request.getAttach());
        wxPayRequest.setSpbillCreateIp(request.getSpbillCreateIp());
        wxPayRequest.setTradeType("APP");
        wxPayRequest.setTimeExpire(request.getTimeExpire());
        wxPayRequest.setNotifyUrl(request.getNotifyUrl());
        WXPayResponse response = unifiedOrder(wxPayRequest);
        //response.setSign(wxPayRequest.getSign());
        return response;
    }

    /*微信支付统一下单*/
    private WXPayResponse unifiedOrder(WXPayRequest wxPayRequest) {
        //配置秘钥信息
        wxPayRequest.setAppid(appId);
        wxPayRequest.setMchId(mchId);
        wxPayRequest.setNotifyUrl(wxPayRequest.getNotifyUrl());
        wxPayRequest.setNonceStr(RandomUtil.getRandomStr());
        wxPayRequest.setTimeExpire(wxPayRequest.getTimeExpire());
        String signKey = mchId;
        /*if(!wxPayProperties.getGateway().endsWith(SANDBOXNEW)){
            signKey = getSignKey();
        }*/

        //签名
        wxPayRequest.setSign(SignatureUtil.sign(BuildDataUtil.buildMap(wxPayRequest), signKey));

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(gateway)
                //xml转化器   SimpleXmlConverterFactory 需要另外添加依赖  不在retrofit2中
                .addConverterFactory(SimpleXmlConverterFactory.create())
                .build();

        String xml = XmlUtil.toXMl(wxPayRequest);
        RequestBody body = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), xml);
        //System.out.println("xml : " + xml);
        Call<WXPayResponse> call = retrofit.create(WXPayRemoting.class).unifiedOrder(body);
        Response<WXPayResponse> retrofitResponse = null;
        try {
            retrofitResponse = call.execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (!retrofitResponse.raw().isSuccessful()) {
            throw new RuntimeException("【微信统一支付】发起支付, 网络异常");
        }
        WXPayResponse response = retrofitResponse.body();

        if (!response.getReturnCode().equals("SUCCESS")) {
            throw new RuntimeException("【微信统一支付】发起支付, returnCode != SUCCESS, returnMsg = " + response.getReturnMsg());
        }
        return response;
    }

    /*微信支付查询接口*/
    public WXOrderQueryResponse query(WXOrderQueryRequest wxQueryRequest) {

        wxQueryRequest.setAppid(appId);
        wxQueryRequest.setMchId(mchId);
        wxQueryRequest.setNonceStr(RandomUtil.getRandomStr());
        String signKey = mchId;
        /*if(!wxPayProperties.getGateway().endsWith(SANDBOXNEW)){
            signKey = getSignKey();
        }*/
        wxQueryRequest.setSign(SignatureUtil.sign(BuildDataUtil.buildMap(wxQueryRequest), signKey));
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(gateway)
                //xml转化器   SimpleXmlConverterFactory 需要另外添加依赖  不在retrofit2中
                .addConverterFactory(SimpleXmlConverterFactory.create())

                .build();
        String xml = XmlUtil.toXMl(wxQueryRequest);
        RequestBody body = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), xml);
        Call<WXOrderQueryResponse> call = retrofit.create(WXPayRemoting.class).query(body);
        Response<WXOrderQueryResponse> retrofitResponse = null;
        try {
            retrofitResponse = call.execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (!retrofitResponse.isSuccessful()) {
            throw new RuntimeException("【微信支付订单查询】查询失败, 网络异常");
        }
        WXOrderQueryResponse response = retrofitResponse.body();

        /*if (!response.getReturnCode().equals("SUCCESS")) {
            throw new RuntimeException("【微信统一支付】发起支付, returnCode != SUCCESS, returnMsg = " + response.getReturnMsg());
        }*/

        return response;
    }

    /*微信支付交易关单接口*/
    public WXPayCloseResponse closeOrder(WXPayCloseRequest wxPayCloseRequest) {
        wxPayCloseRequest.setAppid(appId);
        wxPayCloseRequest.setMchId(mchId);
        wxPayCloseRequest.setNonceStr(RandomUtil.getRandomStr());
        String signKey = mchKey;
       /* if(!wxPayProperties.getGateway().endsWith(SANDBOXNEW)){
            signKey = getSignKey();
        }*/
        wxPayCloseRequest.setSign(SignatureUtil.sign(BuildDataUtil.buildMap(wxPayCloseRequest), signKey));
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(gateway)
                //xml转化器   SimpleXmlConverterFactory 需要另外添加依赖  不在retrofit2中
                .addConverterFactory(SimpleXmlConverterFactory.create())
                .build();
        String xml = XmlUtil.toXMl(wxPayCloseRequest);
        RequestBody body = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), xml);
        Call<WXPayCloseResponse> call = retrofit.create(WXPayRemoting.class).closeOrder(body);
        Response<WXPayCloseResponse> retrofitResponse = null;
        try {
            retrofitResponse = call.execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (!retrofitResponse.isSuccessful()) {
            throw new RuntimeException("【微信支付退款订单查询】查询失败, 网络异常");
        }
        WXPayCloseResponse response = retrofitResponse.body();

        return response;
    }

    /*微信支付退款接口*/
    public WXPayRefundResponse refund(WXPayRefundRequest wxPayRefundRequest, String keyPath) {

        String signKey = mchKey;
       /* if(!wxPayProperties.getGateway().endsWith(SANDBOXNEW)){
            signKey = getSignKey();
        }*/
        wxPayRefundRequest.setSign(SignatureUtil.sign(BuildDataUtil.buildMap(wxPayRefundRequest), signKey));
        //初始化证书
        if (sslProperties.getSslContext() == null) {
            sslProperties.initSSLContext(keyPath, mchId);
        }

        OkHttpClient.Builder okHttpClient = new OkHttpClient()
                .newBuilder()
                .sslSocketFactory(sslProperties.getSslContext().getSocketFactory());

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(gateway)
                .addConverterFactory(SimpleXmlConverterFactory.create())
                .client(okHttpClient.build())
                .build();

        String xml = XmlUtil.toXMl(wxPayRefundRequest);
        System.out.println("refund request body ；" + xml);
        RequestBody body = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), xml);
        Call<WXPayRefundResponse> call = retrofit.create(WXPayRemoting.class).refund(body);
        Response<WXPayRefundResponse> retrofitResponse = null;

        try {
            retrofitResponse = call.execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (!retrofitResponse.isSuccessful()) {
            throw new RuntimeException("【微信退款】发起退款, 网络异常");
        }
        WXPayRefundResponse response = retrofitResponse.body();

        /*if (!response.getReturnCode().equals("SUCCESS")) {
            throw new RuntimeException("【微信退款】发起退款, returnCode != SUCCESS, returnMsg = " + response.getReturnMsg());
        }
        if (!response.getResultCode().equals("SUCCESS")) {
            throw new RuntimeException("【微信退款】发起退款, resultCode != SUCCESS, err_code = " + response.getErrCode() + " err_code_des=" + response.getErrCodeDes());
        }*/

        return response;
    }

    /*微信支付退款查询接口*/
    public WXRefundQueryResponse refundQuery(WXRefundQueryRequest wxRefundQueryRequest) {
        wxRefundQueryRequest.setAppid(appId);
        wxRefundQueryRequest.setMchId(mchId);
        wxRefundQueryRequest.setNonceStr(RandomUtil.getRandomStr());
        String signKey = mchId;
        /*if(!wxPayProperties.getGateway().endsWith(SANDBOXNEW)){
            signKey = getSignKey();
        }*/
        wxRefundQueryRequest.setSign(SignatureUtil.sign(BuildDataUtil.buildMap(wxRefundQueryRequest), signKey));
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(gateway)
                //xml转化器   SimpleXmlConverterFactory 需要另外添加依赖  不在retrofit2中
                .addConverterFactory(SimpleXmlConverterFactory.create())
                .build();
        String xml = XmlUtil.toXMl(wxRefundQueryRequest);
        RequestBody body = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), xml);
        Call<WXRefundQueryResponse> call = retrofit.create(WXPayRemoting.class).refundQuery(body);
        Response<WXRefundQueryResponse> retrofitResponse = null;
        try {
            retrofitResponse = call.execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (!retrofitResponse.isSuccessful()) {
            throw new RuntimeException("【微信支付退款订单查询】查询失败, 网络异常");
        }
        WXRefundQueryResponse response = retrofitResponse.body();

        return response;
    }

    /*沙箱环境获取微信沙箱密钥*/
    public String getSignKey() {
        WXSignkeyRequest signkeyRequest = new WXSignkeyRequest();
        signkeyRequest.setMchId(mchId);
        signkeyRequest.setNonceStr(UUID.randomUUID().toString().replaceAll("-", ""));
        signkeyRequest.setSign(SignatureUtil.sign(BuildDataUtil.buildMap(signkeyRequest),mchKey));
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(gateway)
                //xml转化器   SimpleXmlConverterFactory 需要另外添加依赖  不在retrofit2中
                .addConverterFactory(SimpleXmlConverterFactory.create())
                .build();

        String xml = XmlUtil.toXMl(signkeyRequest);
        RequestBody body = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), xml);
        Call<WXSignkeyResponse> call = retrofit.create(WXPayRemoting.class).getSignKey(body);
        Response<WXSignkeyResponse> retrofitResponse = null;

        try {
            retrofitResponse = call.execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (!retrofitResponse.isSuccessful()) {
            throw new RuntimeException("【微信沙箱】获取沙箱signKey, 网络异常");
        }
        WXSignkeyResponse response = retrofitResponse.body();
        if (!response.getReturnCode().equals("SUCCESS")) {
            throw new RuntimeException("【微信沙箱】获取沙箱signKey, returnCode != SUCCESS, returnMsg = " + response.getReturnMsg());
        }
        return response.getSandboxSignkey();
    }
}
